#include <iostream>
#include <list>
#include <thread>
#include <vector>
#include <algorithm>

#include "stack.h"

/**
 * @brief 测试互斥锁的使用
 */
void test1()
{
    std::list<int> list; // 共享的链表
    std::mutex m; // 互斥锁

    auto add2List = [&list, &m](int nValue)
    {
        std::cout << nValue << std::endl; // 输出当前线程添加的值

        // 没有拿到锁的线程，会等待，直到锁被释放后抢到锁再执行。
        std::lock_guard<std::mutex> lock(m); // 自动加锁和解锁
        list.push_back(nValue); // 安全地向链表添加元素
    };

    auto listContains = [&list, &m](int nValue) -> bool
    {
        std::lock_guard<std::mutex> lock(m); // 自动加锁和解锁
        return std::find(list.begin(), list.end(), nValue) != list.end(); // 安全地检查元素是否存在
    };

    // 创建多个线程添加元素
    std::vector<std::thread> vecThreads;
    for (int i = 0; i < 5; ++i)
    {
        vecThreads.emplace_back([&add2List, i]()
        {
            add2List(i * 10);
        });
    }

    for (auto& thread : vecThreads)
    {
        thread.join(); // 等待所有线程完成
    }

    for (const auto& var : list)
    {
        std::cout << var << " "; // 输出链表内容，随机顺序
    }
    std::cout << std::endl;
}

class SharedList
{
public:
    /**
     * @brief 向链表添加元素
     * @param nValue 值
     */
    void add(int nValue)
    {
        std::lock_guard guard{_mutex}; // 自动加锁和解锁
        _list.push_back(nValue); // 安全地向链表添加元素
    }

    auto& getList()
    {
        std::lock_guard guard{_mutex};
        return _list; // 返回共享的链表
    }

private:
    std::list<int> _list; ///> 共享的链表
    std::mutex _mutex; ///> 互斥锁
};

/**
 * @brief 测试互斥锁的问题
 */
void test2()
{
    SharedList sharedList{}; // 共享的链表对象

    auto threadFunc = [&sharedList]()
    {
        // 线程A安全添加数据
        sharedList.add(10); // 向共享链表添加元素

        // 线程B获得list引用
        auto& ref = sharedList.getList(); // 获取链表引用

        if (!ref.empty())
        {
            std::cout << ref.front() << std::endl;
        }
    };

    std::thread t1(threadFunc);
    std::thread t2(threadFunc);

    t1.join(); // 别忘了等待线程结束
    t2.join();
}

void test3()
{
    MyStack::RegularVersion::stack<int> stk{}; // 创建一个存储整数的栈
    auto func = [&stk]()
    {
        if (!stk.empty())
        {
            auto nValue = stk.top();
            stk.pop();
            std::cout << nValue << std::endl;
        }
    };

    std::thread t1(func);
    std::thread t2(func);
    t1.join();
    t2.join();
}

/**
 * @brief 不同顺序加锁导致死锁
 */
void test4()
{
    auto foo = [](std::mutex& mutex1 , std::mutex& mutex2)
    {
        std::lock_guard<std::mutex> lock1(mutex1);
        std::this_thread::sleep_for(std::chrono::milliseconds(100)); // 模拟一些工作
        std::lock_guard<std::mutex> lock2(mutex2);
    };

    auto bar = [](std::mutex& mutex1 , std::mutex& mutex2)
    {
        std::lock_guard<std::mutex> lock2(mutex2);
        std::this_thread::sleep_for(std::chrono::milliseconds(100));
        std::lock_guard<std::mutex> lock1(mutex1);
    };


    std::mutex mutex1 {} , mutex2 {};
    std::thread t1([&]()
    {
        foo(mutex1, mutex2);
    });

    std::thread t2([&]()
    {
       bar(mutex1, mutex2);
    });

    t1.join();
    t2.join();
}

/**
 * @brief 嵌套锁死锁
 */
void test5()
{
    std::mutex m{};

    auto func = [&m]()
    {
        std::lock_guard guard{m};  // 获取第一把锁
        std::cout << "Locked once" << std::endl;

        std::lock_guard<std::mutex> lock(m); // 尝试获取第二把锁，导致死锁
        std::cout << "Do not execute this line" << std::endl;
    };

    std::thread t1(func);
    t1.join();
}

int main()
{
    // test4();
    test5();
    return 0;
}
